import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.TreeMap;

public class Task03 {
	private static final int SIZE = 1_000_000;
	
	public static void main(String[] args) {
		long memBefore, memAfter;
		
		// =========
		// = array =
		// =========
		
		System.out.println(">>> Building array");
		
		memBefore = Runtime.getRuntime().freeMemory();
		System.out.printf("Before: %,d (total %,d)%n", memBefore, Runtime.getRuntime().totalMemory());
		
		int[] array = new int[SIZE];

		memAfter = Runtime.getRuntime().freeMemory();
		System.out.printf("After:  %,d (total %,d)%n", memAfter, Runtime.getRuntime().totalMemory());
		System.out.printf("Size:   %,d%n", memBefore - memAfter);
		
		// =============
		// = ArrayList =
		// =============
		
		System.out.println("\n>>> Building ArrayList");
		
		memBefore = Runtime.getRuntime().freeMemory();
		System.out.printf("Before: %,d (total %,d)%n", memBefore, Runtime.getRuntime().totalMemory());
		
		ArrayList<Integer> arrayList = new ArrayList<>();
		for (int i = 0; i < array.length; i++) {
			arrayList.add(new Integer(i));
		}

		memAfter = Runtime.getRuntime().freeMemory();
		System.out.printf("After:  %,d (total %,d)%n", memAfter, Runtime.getRuntime().totalMemory());
		System.out.printf("Size:   %,d%n", memBefore - memAfter);
		
		// ==============
		// = LinkedList =
		// ==============
		
		System.out.println("\n>>> Building LinkedList");
		
		memBefore = Runtime.getRuntime().freeMemory();
		System.out.printf("Before: %,d (total %,d)%n", memBefore, Runtime.getRuntime().totalMemory());
		
		LinkedList<Integer> linkedList = new LinkedList<>();
		for (int i = 0; i < array.length; i++) {
			linkedList.add(new Integer(-i));
		}

		memAfter = Runtime.getRuntime().freeMemory();
		System.out.printf("After:  %,d (total %,d)%n", memAfter, Runtime.getRuntime().totalMemory());
		System.out.printf("Size:   %,d%n", memBefore - memAfter);
		
		// ===========
		// = HashMap =
		// ===========
		
		System.out.println("\n>>> Building HashMap");
		
		memBefore = Runtime.getRuntime().freeMemory();
		System.out.printf("Before: %,d (total %,d)%n", memBefore, Runtime.getRuntime().totalMemory());
		
		HashMap<Integer, Integer> hashMap = new HashMap<>();
		for (int i = 0; i < array.length; i++) {
			hashMap.put(new Integer(SIZE + i), new Integer(-SIZE - i));
		}

		memAfter = Runtime.getRuntime().freeMemory();
		System.out.printf("After:  %,d (total %,d)%n", memAfter, Runtime.getRuntime().totalMemory());
		System.out.printf("Size:   %,d%n", memBefore - memAfter);
		
		// ===========
		// = TreeMap =
		// ===========
		
		System.out.println("\n>>> Building TreeMap");
		
		memBefore = Runtime.getRuntime().freeMemory();
		System.out.printf("Before: %,d (total %,d)%n", memBefore, Runtime.getRuntime().totalMemory());
		
		TreeMap<Integer, Integer> treeMap = new TreeMap<>();
		for (int i = 0; i < array.length; i++) {
			treeMap.put(new Integer(2*SIZE + i), new Integer(-2*SIZE - i));
		}

		memAfter = Runtime.getRuntime().freeMemory();
		System.out.printf("After:  %,d (total %,d)%n", memAfter, Runtime.getRuntime().totalMemory());
		System.out.printf("Size:   %,d%n", memBefore - memAfter);
		
		// simulate usage
		Arrays.binarySearch(array, 42);
		arrayList.contains(42);
		linkedList.contains(42);
		hashMap.get(42);
		treeMap.get(42);
	}
	
}
